//
// Created by Arnold on 2021/5/18.
//

#ifndef FRAME_UTIL_H
#define FRAME_UTIL_H


#include "crc.h"

typedef struct
{
    uint16_t dev_num; //设备编号
	uint8_t type;           //命令类型  0x01 同步定时器； 0x02 设置休眠唤醒配置； 0x03 休眠唤醒指令；0x04 电源状态数据；0x05 控制信息;
    uint16_t len;
    uint8_t data[128];
} LoraData;


/**
 * @brief 查找数据包里面的结束字符位置
 * 
 * @param str 原始数据缓冲区
 * @param c 结束字符
 * @param len 原始数据长度
 * @return uint8_t* 找到字符后返回其后部分（包括结尾的空字符）
 */
uint8_t* find_substring(uint8_t *str, uint8_t c, uint16_t len);

/**
 * @brief 编码数据帧：添加帧头、转义字符、CRC 校验和帧尾
 * 
 * @param input 原始数据缓冲区
 * @param input_len 原始数据长度
 * @param output 输出缓冲区指针（由函数分配内存）
 * @return uint16_t 编码后数据长度
 */
uint16_t encode_frame(uint8_t *input, uint16_t input_len, uint8_t **output);

/**
 * @brief 解码数据帧：去除帧头、转义字符、验证 CRC 和帧尾
 * 
 * @param input 接收到的数据缓冲区
 * @param length 接收到的数据长度
 * @param output 输出缓冲区指针（由函数分配内存）
 * @return uint16_t 解码后数据长度，若失败则返回 0
 */
uint16_t decode_frame(uint8_t *input, uint16_t length, uint8_t **output);

/**
 * @brief 解析数据帧，把解决装到结构体数据里面
 * 
 * @param input 需要解析的数据帧
 * @param length 解析的数据长度
 * @return LoraData 解析后的结构体数据
 */
void parse_frame(uint8_t *input, uint16_t length, LoraData *frame);

/**
 * @brief 解析电源系统状态数据，并把数据组装为JSON格式存放到Redis中
 * 
 * @param data 需要解析的数据帧
 */
char *parse_mppt(LoraData data);

/**
 * @brief 存放到Redis中
 * 
 * @param key 需要解析的数据帧
 * @param val 需要解析的数据帧
 */
void push_data(uint8_t *key, uint8_t *val);
#endif //FRAME_UTIL_H
